﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Dev2419a_LunarLander3D
{
    class Nave
    {
        
        /// <summary>
        /// Usado para o motor principal que fica embaixo da nave
        /// </summary>
        private float burst_primary;

        /// <summary>
        /// Usado para os motores secundários que controlam a atitude da nave
        /// </summary>
        private float burst_secundary;

        private int vidasIniciaisNave = 3;
        private int vidas;
        

        // Variáveis da Nave
        private Vector3 posInicialNave;
        private Vector3 posAtualNave;
        private Vector3 posCheckpoint;
        private Vector3 rotInicial = new Vector3(-1.509999f, -0.6299997f, 0.02000001f);
        private Vector3 rot = Vector3.Zero;

        /// <summary>
        /// Módulo da gravidade, deve ser menor que o burst
        /// </summary>
        private float gravityModule;

        /// <summary>
        /// Gravidade
        /// </summary>
        private Vector3 gravity; 
       
        /// <summary>
        /// Velocidade da nave
        /// </summary>
        public Vector3 velocity;

        //fazer a velocidade inicial = 0

        // Câmera
        private Vector3 posCamera;

        private Model modelo;

        private  BasicEffect efeitoBasico;

        private float combustivel = 100f;
        private float oxigenio = 100f;

        
        public Nave(Vector3 posInicial, Model modelo, GraphicsDevice device)
        {
            vidas = vidasIniciaisNave;
            posInicialNave = posInicial;
            posAtualNave = posInicialNave;
            gravityModule = 0.9f;
            burst_primary = 3f;
            burst_secundary = 0.01f;
            gravity = new Vector3(0, -gravityModule, 0);
            velocity = Vector3.Zero;

            this.modelo = modelo;
            this.posCamera = ajustaCameraFromNave(posInicial);

            efeitoBasico = new BasicEffect(device);
                        
            efeitoBasico.Projection = Matrix.CreatePerspectiveFieldOfView(
                /*MathHelper.PiOver4,*/
                MathHelper.ToRadians(45.0f),
                device.Viewport.AspectRatio,
                0.1f, 300.0f);

            efeitoBasico.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 0.1f, 300.0f);

            efeitoBasico.View = Matrix.CreateLookAt( posCamera, Vector3.Zero, Vector3.Up);
            
            Vector3 lightDirection = new Vector3(1.0f, -1.0f, -1.0f);
            lightDirection.Normalize();
            
            //efeitoBasico.Parameters["xLightDirection"].SetValue(lightDirection);
            //efeitoBasico.Parameters["xAmbient"].SetValue(0.1f); efeitoBasico.Parameters["xEnableLighting"].SetValue(true);
            //efeitoBasico.EnableDefaultLighting();
            efeitoBasico.AmbientLightColor = new Vector3(1, 1, 1);
            efeitoBasico.DirectionalLight0.Direction = lightDirection;
            efeitoBasico.DirectionalLight0.Enabled=true;
            efeitoBasico.LightingEnabled = true;

        }

        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            
            modelo.Draw(
                efeitoBasico.World * Matrix.CreateScale(0.20f)
                                   * Matrix.CreateRotationX(rotInicial.X+rot.X)
                                   * Matrix.CreateRotationY(rotInicial.Y+rot.Y)
                                   * Matrix.CreateRotationZ(rotInicial.Z+rot.Z)
                                   * Matrix.CreateTranslation(posAtualNave), 

                efeitoBasico.View ,
                efeitoBasico.Projection  );
            //Console.WriteLine(rot.ToString());
        }

        public void Update(GameTime gameTime, KeyboardState keyState)
        {
            //fazer a nave "cair" com a gravidade
            //posAtual += gravity;//simples demais

            // Tempo passado desde a ultima atualização
            float time = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0f);

            this.oxigenio -= time;

            if (this.combustivel < 0) { this.combustivel = 0; }
            if (this.oxigenio < 0) { this.oxigenio = 0; }
            
            //Atualiza o movimento em X//não tem...
            //posAtual.X += speed.X * time;

            //Atualiza a velocidade Y do objeto ( v = vo + g * t )
            //velocity += gravity * time;
            
            //Console.WriteLine(rot);

            if (keyState.IsKeyDown(Keys.Up) && (combustivel > 0) )
            {
                
                    //posAtual.Y += burst;
                

                float burstX = burst_primary *  (float)Math.Sin((double)rot.X);
                float burstUP = burst_primary * (float)Math.Cos((double)rot.X);

                Console.WriteLine("burst_primary= " + burst_primary.ToString() + ", x=" + burstX.ToString() + " , up=" + burstUP.ToString());

                velocity += (gravity + new Vector3(0, burstUP, burstX)) * time;
                //velocity += (gravity + new Vector3(0, burst_primary, 0)) * time;
                
                    //posAtual += (velocity * time) + (gravity * (float)Math.Pow(time, 2)) * 0.5f;
                    combustivel -= 0.0350f;
               
            }
            //else // esse else tem q ir pra todos
            //{
                velocity += gravity * time;
                combustivel -= 0.001f;
            //}

            //Atualiza a posição Y
            //S = So * t + (g * t*t)/2
            posAtualNave += (velocity * time) + (gravity * (float)Math.Pow(time, 2)) * 0.5f;
            
            //Verifica se atingiu a velocidade máxima de 600.0f//não...
            //speed.Y = (speed.Y > 600.0f) ? 600.0f : speed.Y;

            //TO DO fazer a nave desacelerar com o burst

            if (keyState.IsKeyDown(Keys.W))
            {
                rot.X += burst_secundary;
                //a partir daqui temos que fazer o calculo de sen cos pra acelerar a 
                //nave na direcao certa
            }

            if (keyState.IsKeyDown(Keys.S))
            {
                rot.X -= burst_secundary;
            }

            //if (keyState.IsKeyDown(Keys.A))
            //{
            //    rot.Y += burst_secundary;
            //}

            //if (keyState.IsKeyDown(Keys.D))
            //{
            //    rot.Y -= burst_secundary;
            //}

            if (keyState.IsKeyDown(Keys.Q))
            {
                rot.Z += burst_secundary;
            }

            if (keyState.IsKeyDown(Keys.E))
            {
                rot.Z -= burst_secundary;
            }
            
            //if (keyState.IsKeyDown(Keys.Up))
            //    posAtual.Y += burst;

            //if (keyState.IsKeyDown(Keys.Down))
            //    posAtualNave.Y -= burst;

            //burst para baixo
            if (keyState.IsKeyDown(Keys.Down) && (combustivel > 0))
            {
                velocity -= (gravity + new Vector3(0, burst_primary, 0)) * time;
                combustivel -= 0.07f;
            }

            //NAO SE MEXE MAIS COM A POSICAO DA NAVE DIRETO
            //deve-se deixar a gravidade agir

            //if (keyState.IsKeyDown(Keys.S))
            //    posAtualNave.Z += burst;
            //if (keyState.IsKeyDown(Keys.W))
            //    posAtualNave.Z -= burst;

            //if (keyState.IsKeyDown(Keys.A))
            //    posAtualNave.X += burst;
            //if (keyState.IsKeyDown(Keys.D))
            //    posAtualNave.X -= burst;

            this.posCamera = ajustaCameraFromNave(this.posAtualNave);

            efeitoBasico.View = Matrix.CreateLookAt(posCamera, Vector3.Zero, Vector3.Up);
        }

        public void setPosCamera(Vector3 pos)
        {
            this.posCamera = pos;
        }

        public Vector3 getPosCamera()
        {
            return posCamera;
        }

        public Vector3 getPos()
        {
            return this.posAtualNave;
        }

        public float getVelocidade()
        {
            return this.velocity.Y;
        }

        public float getCombustivel()
        {
            return this.combustivel;
        }

        public float getOxigenio()
        {
            return this.oxigenio;
        }
        
        public int getVidas()
        {
            return this.vidas;
        }
        public void tiraVida()
        {
            this.vidas--;
        }
        public Boolean temVidas()
        {
            return this.vidas>0;
        }

        private Vector3 ajustaCameraFromNave(Vector3 pos)
        {
            return new Vector3(pos.X + 3, pos.Y + 3, pos.Z - 4);
        }


        public void Checkpoint() // Função de resetar a posição da nave para o último checkpoint
        {
            posCheckpoint = posInicialNave;
            posAtualNave = posCheckpoint;
            this.combustivel = 100.0f;
            this.oxigenio = 100.0f;
            velocity = Vector3.Zero;
        }


        public void Reset()
        {
            vidas = vidasIniciaisNave;
            posAtualNave = posInicialNave;
            posCheckpoint = posInicialNave;
            this.combustivel = 100.0f;
            this.oxigenio = 100.0f;
            velocity = Vector3.Zero;
        }
    }
}
